package io.gitee.sfch.chunmi.code.generator.service.impl;


import cn.hutool.core.lang.Assert;
import io.gitee.sfch.chunmi.code.generator.entity.ColumnRef;
import io.gitee.sfch.chunmi.code.generator.entity.JavaType;
import io.gitee.sfch.chunmi.code.generator.entity.TableRef;
import io.gitee.sfch.chunmi.code.generator.service.TableMetaService;
import jakarta.annotation.Resource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
public class MysqlTableMetaService implements TableMetaService {

    @Resource
    private JdbcTemplate jdbcTemplate;

    private static final String TABLE_META_SQL = "SELECT TABLE_NAME, TABLE_COMMENT FROM " +
            "INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?";

    private static final String COLUMN_META_SQL = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS " +
            "WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION";

    @Override
    public String[] supportDriverNames() {
        return new String[]{"com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver"};
    }

    @Override
    public TableRef getTableRef(String schemaName, String tableName) {
        List<TableRef> tableRefs = jdbcTemplate.query(TABLE_META_SQL,
                BeanPropertyRowMapper.newInstance(TableRef.class), schemaName, tableName);
        Assert.notEmpty(tableRefs, "未找到表：" + schemaName + "." + tableName);
        return tableRefs.get(0);
    }

    @Override
    public List<ColumnRef> getColumnRefs(String schemaName, String tableName) {
        return jdbcTemplate.query(COLUMN_META_SQL, BeanPropertyRowMapper.newInstance(ColumnRef.class), schemaName,
                tableName);
    }

    @Override
    public Map<String, JavaType> getJavaTypeMapping() {
        Map<String, JavaType> javaTypeMap = new LinkedHashMap<>();
        javaTypeMap.put("bigint", new JavaType("Long", null));
        javaTypeMap.put("binary", new JavaType("byte[]", null));
        javaTypeMap.put("bit", new JavaType("byte", null));
        javaTypeMap.put("blob", new JavaType("byte[]", null));
        javaTypeMap.put("char", new JavaType("String", null));
        javaTypeMap.put("date", new JavaType("LocalDate", "java.time.LocalDate"));
        javaTypeMap.put("datetime", new JavaType("LocalDateTime", "java.time.LocalDateTime"));
        javaTypeMap.put("decimal", new JavaType("BigDecimal", " java.math.BigDecimal"));
        javaTypeMap.put("double", new JavaType("Double", null));
        javaTypeMap.put("float", new JavaType("Float", null));
        javaTypeMap.put("int", new JavaType("Integer", null));
        javaTypeMap.put("integer", new JavaType("Integer", null));
        javaTypeMap.put("json", new JavaType("String", null));
        javaTypeMap.put("longblob", new JavaType("byte[]", null));
        javaTypeMap.put("longtext", new JavaType("String", null));
        javaTypeMap.put("mediumblob", new JavaType("byte[]", null));
        javaTypeMap.put("mediumtext", new JavaType("String", null));
        javaTypeMap.put("text", new JavaType("String", null));
        javaTypeMap.put("timestamp", new JavaType("Date", "java.util.Date"));
        javaTypeMap.put("tinyblob", new JavaType("byte[]", null));
        javaTypeMap.put("tinyint", new JavaType("Integer", null));
        javaTypeMap.put("tinytext", new JavaType("String", null));
        javaTypeMap.put("varbinary", new JavaType("byte[]", null));
        javaTypeMap.put("varchar", new JavaType("String", null));
        javaTypeMap.put("year", new JavaType("Integer", null));
        return javaTypeMap;
    }

    @Override
    public Map<String, String> getWebTypeMapping() {
        Map<String, String> webTypeMap = new LinkedHashMap<>();
        webTypeMap.put("bigint", "string");
        webTypeMap.put("binary", "string");
        webTypeMap.put("bit", "Number");
        webTypeMap.put("blob", "string");
        webTypeMap.put("char", "string");
        webTypeMap.put("date", "string");
        webTypeMap.put("datetime", "string");
        webTypeMap.put("decimal", "Number");
        webTypeMap.put("double", "Number");
        webTypeMap.put("float", "Number");
        webTypeMap.put("int", "Number");
        webTypeMap.put("integer", "Number");
        webTypeMap.put("json", "string");
        webTypeMap.put("longblob", "string");
        webTypeMap.put("longtext", "string");
        webTypeMap.put("mediumblob", "string");
        webTypeMap.put("mediumtext", "string");
        webTypeMap.put("text", "string");
        webTypeMap.put("timestamp", "string");
        webTypeMap.put("tinyblob", "string");
        webTypeMap.put("tinyint", "string");
        webTypeMap.put("tinytext", "string");
        webTypeMap.put("varbinary", "string");
        webTypeMap.put("varchar", "string");
        webTypeMap.put("year", "Number");
        return webTypeMap;
    }
}
